<?php
/**
 * 父类模型层
 * 继承 PDO
 * @todo 支持对 SQLite 的自定义数据库路径的支持 
 */
namespace phpless\core;

abstract class Model
{
    // 定义属性
    // PDO
    public $pdo;
    // 数据表
    public $table;
    // 主键
    private $pri = '';
    // LIMIT 属性
    private $limit = '';
    // ORDER BY 属性
    private $order = '';
    // GROUP BY 属性
    private $group = '';
    // 字段
    private $fields = array();
    private $all_fields = array();
    // 查询条件 WHERE 属性
    private $where = '';
    // 查询的数据个数
    public $count;
    // 当前查询语句
    public $current_sql = '';
    // 连接数据库
    public function __construct($pdo=null)
    {
        $this -> pdo = $pdo;
    }

    // 测试
    public function display()
    {
        dump('Model OK');
    }

    // 获取表结构
    public function field()
    {
        // 4、定义SQL语句
        $sql = "DESC `{$this -> table}`";
        // 5、执行SQL语句
        $result=$this->pdo-> query($sql);
        // 6、处理查询结果
        if ($result) {
            while($row = $result->fetch(\PDO::FETCH_ASSOC)){
                if ($row['Key'] === 'PRI') {
                    // 获取主键
                    $this -> pri = $row['Field'];
                }else{
                    // 获取除了主键以为的其它字段
                    $this -> fields[] = $row['Field'];
                }
                // 获取所有字段
                $this -> all_fields[] = $row['Field'];
            }
        }
    }

    // 1、生成 where 查询条件
    public function where($condition)
    {
        $where='';
        // 检测 $where 数据类型
        if(is_string($condition)){
            $where=$condition;
        }else if(is_array($condition)){
            // 判断其中键是否是为表的字段、若是、作为搜索条件
            foreach ($condition as $key => $value) {
                if (in_array($key, $this -> fields)) {
                    $where .= "`{$key}`='{$value}' AND ";
                }
            }
            // 除去 $where 的最后一个AND
            $where = rtrim($where,"AND ");
        }else{
            return false;
        }
        // 定义查询语句
        $this -> where = "WHERE {$where} ";
        return $this;
    }
    // 2、设置limit 语句
    public function limit($jump,$num=0)
    {
        // 定义 limit 语句
        if($num==0)
            $limit=$jump;
        else
            $limit="{$jump},{$num}";

        // 定义LIMIT语句
        $this -> limit = "LIMIT {$limit} ";
        return $this;
    }
    // 3、设置 ORDER BY 语句
    public function order($order)
    {
        $order=$order?:$this->pri;
        // 定义查询语句
        $this -> order = "ORDER BY {$order} ";
        return $this;
    }
    // 4、设置 GROUP BY 语句
    public function group($group=null,$having=null)
    {
        if(empty($group) || !is_string($group)){
            return $this;
        }
        // 定义查询语句
        if($having){
            $this -> group = "GROUP BY {$group} HAVING {$having} ";
        }else{
            $this -> group = "GROUP BY {$group} ";
        }
        return $this;
    }

    // 5、获取查询语句的总条数
    public function count()
    {
        $pri=$this->pri;
        // 4、定义SQL语句
        $sql = "SELECT COUNT(`{$pri}`) as count FROM `{$this -> table}` {$this -> where} {$this -> order} {$this -> limit}";
        $this -> current_sql = $sql;
        // 5、执行 SQL 语句
        $result = $this->pdo->query($sql);
        $count = $result->fetch(\PDO::FETCH_ASSOC);
        $this->count=$count['count'];
        return $count['count'];
    }
    // 6、查询所有的记录 $check_field=1 检测 field 0 不检测
    public function select($field=null,$check_field=1)
    {
        $fields='';
        // 格式化需要查询到字符串
        if(empty($field)){
            // 没有则获取所有字段，不用星号 * 表示
            $field=$this->all_fields;
        }
        // 如果是数组转化为字符串
        if(is_array($field)){
            $field=implode(',',$field);
        }
        // 统一转化为数组
        $field=explode(',', $field);
        foreach ($field as $k => &$value) {
            // 过滤非字段字符串
            if($check_field===1){
                $fields_tmp=$this->all_fields;
                if (!in_array($value, $fields_tmp)){
                    unset($field[$k]);
                    continue;
                }
                $value = "`{$value}`";
            }
        }
        $fields=implode(',', $field);
        // 4、定义SQL语句 拼接 WHERE、LIMIT、ORDER BY、GROUP BY 语句 如果有
        $sql = "SELECT {$fields} FROM `{$this -> table}` {$this -> where} {$this -> order} {$this -> group} {$this -> limit}";
        $this -> current_sql = $sql;
        // 5、执行SQL语句
        $result = $this -> pdo -> query($sql);
        $this->resetTable();
        // 6、返回结果
        // 定义空数组
        $rows = array();
        if ($result) {
            // 已索引数据获取查询结果
            $rows = $result -> fetchAll(\PDO::FETCH_ASSOC);
            // 设置查询到的总数
            $this->count=count($rows); // $this->count();
            // 成功返回所查询的数据
            return $rows;
        }else{
            // 失败、返回
            return $result;
        }
    }
    // 6、删除数据
    public function delete($where='')
    {
        if(!empty($where) && is_string($where)){
            $this -> where = "WHERE {$where}";
        }elseif((int)$where>0){
            $id = (int)$where;
            $this -> where = "WHERE {$this -> pri}={$id}";
        }
        if(empty($this -> where)){
            $this->resetTable();
            return false;
        }
        $sql = "DELETE FROM `{$this -> table}` {$this -> where} {$this -> order} {$this -> limit}";
        $this -> current_sql = $sql;
        // 5、执行SQL语句
        $result = $this -> pdo -> exec($sql);
        // 6、返回结果
        $this->resetTable();
        return $result;
    }
    // 7、定义方法、更新一条记录
    public function update($data)
    {
        if(!is_array($data)){
            $this->resetTable();
            return false;
        }
        // 4、过滤 $data 中无效字段
        // 定义空字符串
        $set = "";
        foreach ($data as $key => $value) {
            if (in_array($key, $this -> fields)) {
                // 定义SET语句
                $set .= "`{$key}`='{$value}',";
            }
        }
        // 格式化字符串
        $set = trim($set,",");
        if(empty($set)){
            $this->resetTable();
            return false;
        }
        // 4、定义SQL语句、更新
        // $sql = "UPDATE `{$this -> table}` SET {$set} WHERE {$this -> pri} = {$id}";
        $sql = "UPDATE `{$this -> table}` SET {$set} {$this -> where} {$this -> limit}";
        $this -> current_sql = $sql;
        // 5、执行SQL语句
        $result = $this -> pdo -> exec($sql);
        $this->resetTable();
        return $result;
    }
    // 8、定义方法、查询单条数据
    public function find($id=0,$field='*')
    {
        if(empty($field)){
            $this->resetTable();
            return false;
        }
        $fields='';
        // 格式化需要查询到字符串
        if($field==='*'){
            // 没有则获取所有字段，不用星号 * 表示
            $field=$this->all_fields;
        }
        // 如果是数组转化为字符串
        if(is_array($field)){
            $field=implode(',',$field);
        }

        // 统一转化为数组
        $field=explode(',', $field);
        foreach ($field as $k => &$value) {
            // 过滤非字段字符串
            $fields_tmp=$this->all_fields;
            if (!in_array($value, $fields_tmp)) {
                unset($field[$k]);
                continue;
            }
            $value = "`{$value}`";
        }
        $fields=implode(',', $field);

        // 4、定义SQL语句
        if(empty($id)){
            $sql = "SELECT {$fields} FROM `{$this -> table}` {$this -> where} {$this -> order} LIMIT 1";
        }else{
            $sql = "SELECT {$fields} FROM `{$this -> table}` WHERE {$this -> pri} = {$id}";
        }

        $this -> current_sql = $sql;
        // 5、执行SQL语句
        $result = $this->pdo->query($sql);
        // 6、处理查询结果
        if($result){
            $result = $result -> fetch(\PDO::FETCH_ASSOC);
        }
        $this->resetTable();
        return $result;
    }
    // 定义方法、添加记录
    public function insert($data)
    {
        // 定义空字符串
        $key_list = $value_list = '';
        // 根据数组、用于定义SQL语句
        foreach ($data as $key => $value) {
            if (in_array($key, $this -> all_fields)) {
                $key_list .= "`{$key}`,";
                $value_list .= "'{$value}',";
            }
        }
        // 过滤两端,
        $key_list = trim($key_list,',');
        $value_list = trim($value_list,',');
        // 4、定义SQL语句
        $sql = "INSERT INTO `{$this -> table}` ({$key_list}) VALUES ($value_list)";
        $this -> current_sql = $sql;
        // 5、执行SQL语句
        $result = $this -> pdo -> exec($sql);
        if($result !== false){
            $result = $this -> pdo -> lastInsertId();
        }
        $this->resetTable();
        return $result;
    }

    // 分页、第一种方式 $page=页码 $page_total=每页数量
    public function paginator($page_total=20,$field=null)
    {
        // 当前页
        $page=isset($_GET['p'])?(int)$_GET['p']:1;
        $count=$this->count();
        // 一共页数
        $pages=ceil($count/$page_total);
        if($page<=0){
            $page=1;
        }elseif($page>$pages){
            $page=$pages;
        }
        $start=($page-1)*$page_total;
        $data_temp=$this->limit($start,$page_total)->select($field);

        // 分页参数
        $paginate_data['current_page']=(int)$page;
        $paginate_data['last_page']=(int)$pages;
        $paginate_data['totals']=(int)$count;
        $paginate_data['list_rows']=(int)count($data_temp);

        if($paginate_data['current_page']==$paginate_data['last_page']){
            $paginate_data['has_more']=false;
        }else{
            $paginate_data['has_more']=true;
        }
        $paginate_data['next_page']=(int)$paginate_data['current_page']+1;
        $data['data']=$data_temp;
        unset($data_temp);
        $data['paginate_data']=$paginate_data;
        $this->resetTable();
        return $data;
    }

    // 分页、第二种方式 $page=页码 $page_total=每页数量
    public function paginator2($page_total=20,$field=null)
    {
        $pri = $this->pri;
        // 当前页
        $page=isset($_GET['p'])?(int)$_GET['p']:1;
        // 原 ORDER BY
        $order=$this->order;
        if(empty($order)){
            $order="ORDER BY {$pri}";
        }
        $order=$order.' ';
        if(stripos($order," {$pri} ")===false){
            $this->resetTable();
            return false;
        }
        // 原 WHERE
        $where = $this -> where;
        if(stripos($order,'desc')){
            // 逆序检索
            $first_data=$this->order("{$pri} DESC")->find(0,'id');
            // 恢复原来 WHERE
            $this -> where = $where;
            $last_data=$this->order("{$pri} ASC")->find(0,'id');
            if(empty($first_data) || empty($last_data)){
                $this->resetTable();
                return false;
            }
            $first_data_id=$first_data[$pri];
            $last_data_id=$last_data[$pri];
            // 数据量
            $count=$first_data_id-$last_data_id+1;
            // 一共页数
            $pages=ceil($count/$page_total);

            if($page<=0){
                $page=1;
            }elseif($page>$pages){
                $page=$pages;
            }

            $start=$first_data_id-($page-1)*$page_total;
            $end=$first_data_id-$page*$page_total+1;
            $paginator_where="id<={$start} AND id>={$end}";
        }else{
            // 正序检索
            $first_data=$this->order("{$pri} ASC")->find(0,'id');
            // 恢复原来 WHERE
            $this -> where = $where;
            $last_data=$this->order("{$pri} DESC")->find(0,'id');
            if(empty($first_data) || empty($last_data)){
                $this->resetTable();
                return false;
            }
            $first_data_id=$first_data[$pri];
            $last_data_id=$last_data[$pri];
            // 数据量
            $count=$last_data_id-$first_data_id+1;
            // 一共页数
            $pages=ceil($count/$page_total);
            if($page<=0){
                $page=1;
            }elseif($page>$pages){
                $page=$pages;
            }
            $start=($page-1)*$page_total+$first_data_id;
            $end=$page*$page_total+$first_data_id-1;
            $paginator_where="id>={$start} AND id<={$end}";
        }
        $this -> order = $order;
        if(empty($where)){
            $this -> where = "WHERE {$paginator_where}";
        }else{
            $this -> where = "{$where} AND {$paginator_where}";
        }
        $data_temp=$this->select($field);
        // 恢复原来 WHERE
        $this -> where = $where;
        // 分页参数
        $paginate_data['current_page']=(int)$page;
        $paginate_data['last_page']=(int)$pages;
        $paginate_data['totals']=(int)$count;
        $paginate_data['list_rows']=(int)count($data_temp);

        if($paginate_data['current_page']==$paginate_data['last_page']){
            $paginate_data['has_more']=false;
        }else{
            $paginate_data['has_more']=true;
        }
        $paginate_data['next_page']=(int)$paginate_data['current_page']+1;
        $data['data']=$data_temp;
        unset($data_temp);
        $data['paginate_data']=$paginate_data;
        $this->resetTable();
        return $data;
    }
    // 初始化数据表各项属性、链式操作重复使用
    public function resetTable()
    {
        $this -> limit = '';
        // ORDER BY 属性
        $this -> order = '';
        // GROUP BY 属性
        $this -> group = '';
        // 查询条件 WHERE 属性
        $this -> where = '';
        return true;
    }
    // === 预处理语句 ===
    // 添加操作
    public function preInsert($data)
    {
        // 定义空字符串
        $key_list = $value_list = '';
        // 根据数组、用于定义 SQL 预处理语句
        foreach ($data as $key => $value) {
            if (in_array($key, $this -> all_fields)) {
                $key_list .= "`{$key}`,";
                $value_list .= ":{$key},";
                $bind_param[$key] = $value;
            }
        }
        if(empty($bind_param)){
            return false;
        }
        // 过滤两端,
        $key_list = trim($key_list,',');
        $value_list = trim($value_list,',');
        // 定义预处理 SQL 语句
        $sql = "INSERT INTO `{$this -> table}` ({$key_list}) VALUES ($value_list)";
        // 生成 PDOStatement 对象，准备处理预处理语句
        $pdo_statement = $this -> pdo -> prepare($sql);
        // 绑定参数
        foreach($bind_param as $k => $v){
            $pdo_statement->bindParam(":{$k}",$$k);
            $$k = $v;
        }
        // 执行SQL语句
        $result = $pdo_statement->execute();
        // 查看并处理结果集
        if($result){
            $result = $this -> pdo -> lastInsertId();
        }
        $this -> current_sql = $sql;
        $this->resetTable();
        return $result;
    }
    // 删除操作
    public function preDelete($data,$where='')
    {
        if(empty($this -> where) && !empty($where) && is_string($where)){
            $this -> where = "WHERE {$where}";
        }elseif(empty($this -> where)){
            $this -> where = "WHERE {$this -> pri}=:{$this -> pri}";
        }
        if(empty($this -> where)){
            $this->resetTable();
            return false;
        }

        if(is_int($data)){
            $bind_param[$this -> pri] = (int)$data;
        }elseif(is_array($data)){
            foreach ($data as $key => $value) {
                if (strpos($this -> where,$key)) {
                    $bind_param[$key] = $value;
                }
            }
        }else{
            $this->resetTable();
            return false;
        }

        // 定义预处理 SQL 语句
        $sql = "DELETE FROM `{$this -> table}` {$this -> where} {$this -> order} {$this -> limit}";
        $this -> current_sql = $sql;
        // 生成 PDOStatement 对象，准备预处理语句
        $pdo_statement = $this -> pdo -> prepare($sql);
        // 绑定参数
        foreach($bind_param as $k => $v){
            if(strpos($k,':') === 0){
                $pdo_statement -> bindParam("{$k}",$$k);
            }else{
                $pdo_statement -> bindParam(":{$k}",$$k);
            }
            $$k = $v;
        }
        // 执行 SQL 语句
        $result = $pdo_statement -> execute();
        // 查看并处理结果集
        if($result){
            $result = $pdo_statement -> rowCount();
        }
        $this->resetTable();
        // 返回结果
        return $result;
    }
    // 修改操作
    public function preUpdate($data,$where=[])
    {
        if(empty($data) && !is_array($data)){
            $this->resetTable();
            return false;
        }

        $bind_param=[];
        if(!empty($this -> where) && !empty($where) && is_array($where)){
            foreach($where as $k => $v){
                if (strpos($this -> where,$k)) {
                    // 定义绑定参数
                    $bind_param[$k] = $v;
                }
            }
        }
        $bind_param_set = '';
        foreach ($data as $key => $value) {
            if (in_array($key,$this -> all_fields)) {
                // 定义 SET 语句
                $bind_param_set .= "`{$key}`=:this_update_{$key},";
                // 定义绑定参数
                $bind_param["this_update_{$key}"] = $value;
            }
        }
        // 格式化字符串
        $bind_param_set = trim($bind_param_set,",");
        if(empty($bind_param_set)){
            $this->resetTable();
            return false;
        }

        // 定义预处理 SQL 语句
        $sql = "UPDATE `{$this -> table}` SET {$bind_param_set} {$this -> where} {$this -> order} {$this -> limit}";
        $this -> current_sql = $sql;
        // 生成 PDOStatement 对象，准备预处理语句
        $pdo_statement = $this->pdo->prepare($sql);
        // 绑定参数
        foreach($bind_param as $k => $v){
            if(strpos($k,':') === 0){
                $pdo_statement -> bindParam("{$k}",$$k);
            }else{
                $pdo_statement -> bindParam(":{$k}",$$k);
            }
            $$k = $v;
        }
        // 执行 SQL 语句、生成 PDOStatement 对象，准备预处理语句
        $result = $pdo_statement->execute();
        if($result){
            $result = $pdo_statement->rowCount();
            $this -> count = $result;
        }
        // 返回结果
        $this->resetTable();
        return $result;
    }
    // 查询操作
    public function preSelect($where=null,$field=null,$check_field=1)
    {
        $fields='';
        // 格式化需要查询到字符串
        if(empty($field)){
            // 没有则获取所有字段，不用星号 * 表示
            $field=$this->all_fields;
        }
        // 如果是数组转化为字符串
        if(is_array($field)){
            $field=implode(',',$field);
        }
        // 统一转化为数组
        $field=explode(',', $field);
        foreach ($field as $k => &$value) {
            // 过滤非字段字符串
            if($check_field===1){
                $fields_tmp=$this->all_fields;
                if (!in_array($value, $fields_tmp)){
                    unset($field[$k]);
                    continue;
                }
                $value = "`{$value}`";
            }
        }
        $fields=implode(',', $field);

        $bind_param=[];
        if(!empty($this -> where) && !empty($where) && is_array($where)){
            foreach($where as $k => $v){
                if (strpos($this -> where,$k)) {
                    // 定义绑定参数
                    $bind_param[$k] = $v;
                }
            }
        }

        // 定义 SQL 预处理语句
        $sql = "SELECT {$fields} FROM `{$this -> table}` {$this -> where} {$this -> order} {$this -> group} {$this -> limit}";
        $this -> current_sql = $sql;
        // 生成 PDOStatement 对象，准备预处理语句
        $pdo_statement = $this->pdo->prepare($sql);
        // 绑定参数
        foreach($bind_param as $k => $v){
            if(strpos($k,':') === 0){
                $pdo_statement -> bindParam("{$k}",$$k);
            }else{
                $pdo_statement -> bindParam(":{$k}",$$k);
            }
            $$k = $v;
        }
        // 执行 SQL 语句
        $pdo_statement->execute();
        // 查看并处理结果集
        $result = $pdo_statement->rowCount();
        $this -> count = $result;
        if($result){
            // 以索引数据获取查询结果
            $result = $pdo_statement -> fetchAll(\PDO::FETCH_ASSOC);
        }
        $this->resetTable();
        return $result;
    }
    // 单条查询
    public function preFind($where=null,$field=null)
    {
        $fields='';
        // 格式化需要查询到字符串
        if(empty($field)){
            // 没有则获取所有字段，不用星号 * 表示
            $field=$this->all_fields;
        }
        // 如果是数组转化为字符串
        if(is_array($field)){
            $field=implode(',',$field);
        }
        // 统一转化为数组
        $field=explode(',', $field);
        foreach ($field as $k => &$value) {
            // 过滤非字段字符串
            $fields_tmp=$this->all_fields;
            if (!in_array($value, $fields_tmp)) {
                unset($field[$k]);
                continue;
            }
            $value = "`{$value}`";
        }
        $fields=implode(',', $field);

        $bind_param=[];
        if(!empty($this -> where) && !empty($where) && is_array($where)){
            foreach($where as $k => $v){
                if (strpos($this -> where,$k)) {
                    // 定义绑定参数
                    $bind_param[$k] = $v;
                }
            }
        }

        // 定义 SQL 预处理语句
        $sql = "SELECT {$fields} FROM `{$this -> table}` {$this -> where} {$this -> order} LIMIT 1";
        $this -> current_sql = $sql;
        // 生成 PDOStatement 对象，准备预处理语句
        $pdo_statement = $this->pdo->prepare($sql);
        // 绑定参数
        foreach($bind_param as $k => $v){
            if(strpos($k,':') === 0){
                $pdo_statement -> bindParam("{$k}",$$k);
            }else{
                $pdo_statement -> bindParam(":{$k}",$$k);
            }
            $$k = $v;
        }
        // 执行 SQL 语句
        $pdo_statement->execute();
        // 查看并处理结果集
        $result = $pdo_statement->rowCount();
        $this -> count = $result;
        if($result){
            // 以索引数据获取查询结果
            $result = $pdo_statement -> fetch(\PDO::FETCH_ASSOC);
        }
        $this->resetTable();
        return $result;
    }
    // === 直接执行 SQL 语句、自动判断是否是预处理 ===
    // 增、删、改、查 $data=null 未使用预处理
    public function executeSql($sql,$data=null)
    {
        $result = false;
        $sql = trim($sql);
        // 判断数据库操作类型
        $execute_type = strtolower(trim(explode(' ',$sql)[0]));
        // 判断是否为预处理
        if(empty($data)){
            if($execute_type === 'select'){
                $query_result = $this -> pdo -> query($sql);
                $result = array();
                if ($query_result) {
                    // 已索引数据获取查询结果
                    $result = $query_result -> fetchAll(\PDO::FETCH_ASSOC)?:[];
                }
                // 设置查询到的总数
                $this -> count = count($result);
            }else{
                $result = $this -> pdo -> exec($sql);
                if($execute_type === 'insert' && $result){
                    $result = $this -> pdo -> lastInsertId();
                }
            }
        }else{
            // 生成 PDOStatement 对象，准备处理预处理语句
            $pdo_statement = $this -> pdo -> prepare($sql);
            // 绑定参数
            foreach($data as $k => $v){
                if(strpos($k,':') === 0){
                    $pdo_statement -> bindParam("{$k}",$$k);
                }else{
                    $pdo_statement -> bindParam(":{$k}",$$k);
                }
                $$k = $v;
            }
            // 执行SQL语句
            $execute_result = $pdo_statement -> execute();
            $result = $pdo_statement -> rowCount();
            $this -> count = $result;
            if($execute_type === 'select'){
                $rows = [];
                if($result){
                    // 以索引数据获取查询结果
                    $rows = $pdo_statement -> fetchAll(\PDO::FETCH_ASSOC)?:[];
                }
                $result = $rows;
            }elseif($execute_type === 'insert'){
                $result = $this -> pdo -> lastInsertId();
            }
        }
        $this -> current_sql = $sql;
        return $result;
    }
    // 单条查
    public function executeFind($sql,$data=null)
    {
        $result = false;
        $sql = trim($sql);
        // 判断数据库操作类型
        if(stripos($sql, 'SELECT') !== 0){
            return $result;
        }
        // 判断是否为预处理
        if(empty($data)){
            $query_result = $this -> pdo -> query($sql);
            $result = array();
            if ($query_result) {
                // 已索引数据获取查询结果
                $result = $query_result -> fetch(\PDO::FETCH_ASSOC);
                // 设置查询到的总数
                $this -> count = count($result);
            }
        }else{
            // 生成 PDOStatement 对象，准备处理预处理语句
            $pdo_statement = $this -> pdo -> prepare($sql);
            // 绑定参数
            foreach($data as $k => $v){
                $pdo_statement -> bindValue("{$k}",$v);
            }
            // 执行SQL语句
            $execute_result = $pdo_statement -> execute();
            $result = $pdo_statement -> rowCount();
            $this -> count = $result;
            $row = [];
            if($result){
                // 以索引数据获取查询结果
                $row = $pdo_statement -> fetch(\PDO::FETCH_ASSOC);
            }
            $result = $row;
        }
        $this -> current_sql = $sql;
        return $result;
    }
    // 批量添加操作 预处理
    public function preInsertAll($data)
    {
        $result = array(
            'status' => 0,
            'info' => '批量数据插入',
            'insert_id' => []
        );
        // 定义空字符串
        $key_list = $value_list = '';
        // 根据数组、用于定义 SQL 预处理语句
        $bind_param = [];
        foreach($data as $v){
            if(!is_array($v) && empty($v)){
                $result['info'] = '传入数组格式不正确';
                return $result;
            }
            foreach ($v as $key => $value) {
                $key_list .= "`{$key}`,";
                $value_list .= ":{$key},";
                if (in_array($key, $this -> all_fields)) {
                    $bind_param[] = $key;
                }
            }
            break;
        }
        if(empty($bind_param)){
            $result['info'] = '传入数组中的字段不能为空';
            return $result;
        }
        // 过滤两端,
        $key_list = trim($key_list,',');
        $value_list = trim($value_list,',');
        // 定义预处理 SQL 语句
        $sql = "INSERT INTO `{$this -> table}` ({$key_list}) VALUES ($value_list)";
        // 生成 PDOStatement 对象，准备处理预处理语句
        $pdo_statement = $this -> pdo -> prepare($sql);
        // 绑定参数
        $execute_count = array();
        $ids = array();
        foreach ($bind_param as $value) {
            $pdo_statement->bindParam(":{$value}",$$value);
        }
        foreach($data as $v){
            foreach ($v as $key => $value) {
                // 参数赋值
                $$key = $value;
            }
            // 执行SQL语句
            $execute_result = $pdo_statement->execute();
            $execute_count[] = $execute_result?1:0;
            // 获取当前插入 id
            $ids[] = $this -> pdo -> lastInsertId();
        }
        $result_sum = array_sum($execute_count);
        $this -> current_sql = $sql;
        $this->resetTable();
        $result = array(
            'status' => $result_sum,
            'info' => '批量数据插入',
            'insert_ids' => $ids
        );
        return $result;
    }
    // 批量添加操作 预处理 别名
    public function insertAll($data)
    {
        return $this -> preInsertAll($data);
    }
    // 7、关闭数据库、析构函数
    public function __destruct()
    {
        // 关闭数据库 自动关闭
    }
}
